
   
   //程序功能：使用状态机根据通道连接 链路连接的状态产生系统复位信号和收发器复位信号。
   //程序的目的：因为AURORA核的复位时序，官方有要求，所以我们单独编写一个模块，完成该时序的产生。


	`timescale 1ns / 1ps

	module gtp_reset_control(
		input	wire 			clk 				,
		input 	wire 			rst 				,

		input 	wire 			channel_link_up 	,// 通道链接信号
		input 	wire 			lane_link_up 		,// lane 链接信号 

		output 	wire 			reset 				,// 系统复位
		output 	wire 			gt_reset 	 		 // 收发器复位
		);

	//==========================================
	//parameter define
	//==========================================
	parameter IDLE = 3'b001; //上电状态
	parameter RESET = 3'b010; //GTP复位状态
	parameter DETECT = 3'b100; //检测LINK状态

	parameter RESET_MAX = 384 ;
	parameter GT_RESET_MAX = 128  ;


	//==========================================
	//internal signals
	//==========================================
	reg 	[2:0]	state 			;
	reg 			reset_r 		;//系统复位信号
	reg 			gt_reset_r 		;//收发器复位信号

	wire 			link_flag 		;//用于判断当前是否链接
	reg 	[1:0]	link_flag_dd 	;//link 延时信号
	reg 	[10:0]	cnt_rst 		;//用于产生复位信号的计数器
	wire			add_cnt_rst		;
	wire 			end_cnt_rst 	;

    //相当于是一个总的链接指示信号
	assign link_flag = channel_link_up & lane_link_up;
	
	//将我们自己产生的系统复位信号，和收发器的复位信号引出去。
	assign reset = reset_r;        //系统复位信号 
	assign gt_reset = gt_reset_r;  // 收发器复位信号


	//----------------state machine describe------------------
	always @(posedge clk) begin
		if (rst==1'b1) begin
			state <= IDLE ;
		end
		else begin
			case(state )
				IDLE : begin //当前状态机处于空闲状态
					state <= RESET;
				end

				RESET : begin
					if (end_cnt_rst == 1'b1) begin//表示在该复位状态 等待了一段时间之后
						state <= DETECT;
					end
					else begin
						state <= RESET;
					end
				end

				DETECT : begin
					//检测到link状态出现下降沿  如果监测到链路链接状态断开，重新进入到复位状态，否则状态保持
					if (link_flag_dd[0] == 1'b0 && link_flag_dd[1] == 1'b1) begin
						state <= RESET;
					end
					else begin
						state <= DETECT;
					end
				end

				default : begin
					state <= IDLE ;
				end
			endcase
		end
	end

	//----------------cnt_rst ------------------
	always @(posedge clk) begin
		if (rst == 1'b1) begin
			cnt_rst <= 'd0;
		end
		else if (add_cnt_rst) begin //当前处于复位状态，计数器延迟一段时间之后
			if(end_cnt_rst)
				cnt_rst <= 'd0;
			else
				cnt_rst <= cnt_rst + 1'b1;
		end
		else begin
			cnt_rst <= 'd0;
		end
	end

    //
	assign add_cnt_rst = state == RESET;
	assign end_cnt_rst = add_cnt_rst &&	cnt_rst == RESET_MAX - 1; //当状态机处于复位状态，计数器会进行计数，这里等待一段时间结束后

	//----------------link_flag_dd------------------
	always @(posedge clk) begin
		if (rst==1'b1) begin
			link_flag_dd <= 'd0;
		end
		else begin
			link_flag_dd <= {link_flag_dd[0], link_flag};
		end
	end

	//----------------gt_reset_r------------------
	always @(posedge clk) begin
		if (rst==1'b1) begin
			gt_reset_r <= 1'b1;
		end
		else if (link_flag_dd[0] == 1'b0 && link_flag_dd[1] == 1'b1) begin
			gt_reset_r <= 1'b1;
		end
		else if (state == RESET && cnt_rst == GT_RESET_MAX - 1) begin
			gt_reset_r <= 1'b0;
		end
	end

	//----------------reset_r------------------
	always @(posedge clk) begin
		if (rst==1'b1) begin
			reset_r <= 1'b1;
		end
		else if (link_flag_dd[0] == 1'b0 && link_flag_dd[1] == 1'b1) begin
			reset_r <= 1'b1;
		end
		else if (state == RESET && cnt_rst == RESET_MAX - 1) begin
			reset_r <= 1'b0;
		end
	end
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	endmodule